home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q0429.dms / q0429.adf / libray / libsurf / surfshade.c < prev   
C/C++ Source or Header  |  1992-05-20  |  5KB  |  196 lines

  1. /*
  2.  * surfshade.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: surfshade.c,v 4.0.1.2 92/01/10 14:08:28 cek Exp Locker: cek $
  17.  *
  18.  * $Log:    surfshade.c,v $
  19.  * Revision 4.0.1.2  92/01/10  14:08:28  cek
  20.  * patch3: Fixed additional composition problems.
  21.  * 
  22.  * Revision 4.0.1.1  91/12/13  11:54:51  cek
  23.  * patch3: Fixed ordering of world/model xform composition.
  24.  * patch3: Geometric normal now transformed correctly.
  25.  * 
  26.  * Revision 4.0  91/07/17  14:41:15  kolb
  27.  * Initial version.
  28.  * 
  29.  */
  30. #include "libobj/geom.h"
  31. #include "surface.h"
  32.  
  33. /*
  34.  * Compute surface properties from given hitlist
  35.  * Returns TRUE if ray is entering object, FALSE otherwise.
  36.  */
  37. int
  38. ComputeSurfProps(hitlist, ray, pos, norm, gnorm, surf, smooth)
  39. HitList *hitlist;    /* Hit information (path through DAG) */
  40. Ray *ray;        /* Ray in world space */
  41. Vector *pos;        /* Intersection point */
  42. Vector *norm, *gnorm;    /* shading normal, geometric normal (return values) */
  43. Surface *surf;        /* Copy of surface to use, texture-modified */
  44. int *smooth;
  45. {
  46.     HitNode *hp;
  47.     int i;
  48.     Ray rtmp;
  49.     Geom *prim, *obj;
  50.     Float k, kp;
  51.     int texturing, transforming, entering;
  52.     Trans prim2model, world2model;
  53.  
  54.     hp = hitlist->data;
  55.     prim = hp->obj;
  56.  
  57.     /*
  58.      * Compute point of intersection in "primitive space".
  59.      */
  60.     VecAddScaled(hp->ray.pos, hp->dist, hp->ray.dir, pos);
  61.  
  62.     /*
  63.      * Find normal to primitive at point of intersection.
  64.      */
  65.     *smooth = PrimNormal(prim, pos, norm, gnorm);
  66.  
  67.     texturing = transforming = FALSE;
  68.  
  69.     /*
  70.      * Walk down hit list, constructing world<-->primitive transformation
  71.      * and determining if we need to perform texture mapping.
  72.      * The last node is the World node, which cannot be textured or
  73.      * transformed, so we skip it.
  74.      */
  75.     for (i = 0, hp = hitlist->data; i < hitlist->nodes -1; hp++, i++) {
  76.         obj = hp->obj;
  77.         texturing = texturing || obj->texture;
  78.         if (hp->dotrans) {
  79.             /*
  80.              * Here we're actually computing prim2world.
  81.              * When finished, we invert it.
  82.              */
  83.             if (transforming) {
  84.                 TransCompose(&world2model, &hp->trans,
  85.                     &world2model);
  86.             } else {
  87.                 TransCopy(&hp->trans, &world2model);
  88.                 transforming = TRUE;
  89.             }
  90.         }
  91.     }
  92.  
  93.     /*
  94.      * Determine if we're entering or exiting the surface,
  95.      * flipping surface normals if necessary.
  96.      */
  97.     k = dotp(&hitlist->data[0].ray.dir, norm);
  98.     if (*smooth) {
  99.         /*
  100.          * If gnorm and shading norm differ and
  101.          * their dot products with the ray have
  102.          * different signs, use the geometric normal
  103.          * instead, ala Snyder & Barr's paper.
  104.          */
  105.         kp = dotp(&hitlist->data[0].ray.dir, gnorm);
  106.         if (k <= 0. && kp > 0. || k >= 0. && kp < 0.)
  107.             k = kp;
  108.     }
  109.  
  110.     if (k > 0.) {
  111.         /* flip normals */
  112.         VecScale(-1., *gnorm, gnorm);
  113.         VecScale(-1., *norm, norm);
  114.         /*
  115.          * Normal indicates that we're exiting.
  116.          * Only set entering to TRUE if csg has indicated
  117.          * that the ray is, indeed, entering.
  118.          */
  119.         entering = (hitlist->data[0].enter == ENTERING);
  120.     } else {
  121.         /*
  122.          * Normal indicates that we're entering.
  123.          * Set entering flag as such unless csg has
  124.          * told us that we're exiting.
  125.          */
  126.         entering = !(hitlist->data[0].enter == EXITING);
  127.     }
  128.         
  129.     /*
  130.      * If there are no transformations, then world2model is identity.
  131.      */
  132.     if (!transforming)
  133.         TransInit(&world2model);
  134.     /*
  135.      * If we're not performing texturing, we simply need to compute
  136.      * the normal and point of intersection to world space.
  137.      */
  138.     if (!texturing) {
  139.         /*
  140.           * At this point 'world2model' is really 'prim2world'.
  141.          */
  142.         if (transforming) {
  143.             NormalTransform(norm, &world2model.itrans);
  144.             NormalTransform(gnorm, &world2model.itrans);
  145.             VecAddScaled(ray->pos,
  146.                      hitlist->data[hitlist->nodes -1].dist,
  147.                      ray->dir, pos);
  148.         }
  149.         return entering;
  150.     }
  151.     /*
  152.      * world2model currently transforms from primitive to world space.
  153.      * Invert it to get transformation from world to primitive space.
  154.      */
  155.     TransInvert(&world2model, &world2model);
  156.     TransInit(&prim2model);
  157.     rtmp = hitlist->data[0].ray;
  158.     /*
  159.      * Walk down hitlist (from primitive up to World object),
  160.      * transforming hit point and shading normal and applying textures.
  161.      * Note that the texturing routines want gnorm in object space,
  162.      * so we don't transform the geometric normal until texturing
  163.      * is complete.
  164.      */
  165.     for (hp = hitlist->data, i = 0; i < hitlist->nodes -1; i++, hp++) {
  166.         obj = hp->obj;
  167.         if (hp->dotrans) {
  168.             NormalTransform(norm, &hp->trans.itrans);
  169.             if (texturing) {
  170.                 /*
  171.                  * Compose prim<-->model and world<-->model
  172.                  * with current transformation.
  173.                  */
  174.                 TransCompose(&prim2model, &hp->trans,
  175.                     &prim2model);
  176.                 TransCompose(&world2model, &hp->trans,
  177.                     &world2model);
  178.                 /*
  179.                  * Transform point and ray to model space.
  180.                  */
  181.                 PointTransform(pos, &hp->trans.trans);
  182.                 (void)RayTransform(&rtmp, &hp->trans.trans);
  183.             }
  184.         }
  185.         /*
  186.          * Apply textures
  187.          */
  188.         if (obj->texture)
  189.             TextApply(obj->texture, prim, &rtmp, pos, norm,
  190.                 gnorm, surf, &prim2model, &world2model);
  191.     }
  192.     /* Transform geometric normal from object to world space. */
  193.     NormalTransform(gnorm, &world2model.trans);
  194.     return entering;
  195. }
  196.